package facade;

import facade.exception.IncorrectPasswordException;
import facade.exception.NotExistingObjectException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import service.ServiceFactory;
import service.exception.ObjectNotFoundException;
import valueObject.*;
import valueObjetcsView.ResultObject;

@Stateless
@LocalBean
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class SuiLibFacade {

    @PersistenceContext
    EntityManager em;
    
    /*
     *
     * Metodos de los cursos
     * 
     */

    public List<CourseVO> getAllCoursesVO(){
        return ServiceFactory.getInstance().getCourseService().findAll(em);
    }
    
    public List<CourseVO> getAllCoursesVOInRange(int bein, int end){
        return ServiceFactory.getInstance().getCourseService().findRange(bein, end, em);
    }
    
    public CourseVO getCourseVOById(int id) throws NotExistingObjectException{
        try {
            return ServiceFactory.getInstance().getCourseService().findById(id, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
            
    public void createCourse(CourseVO courseVO){
        ServiceFactory.getInstance().getCourseService().create(courseVO, em);
    }
    
    public void updateCourse(CourseVO courseVO) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getCourseService().update(courseVO, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public void deleteCourse(int id) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getCourseService().delete(id, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public List<CourseVO> findCoursesByCategory(CategoryVO categoryVO){
        return ServiceFactory.getInstance().getCourseService().findCourseByCategory(categoryVO, em);
    }
    
    public List<CourseVO> findCoursesByUniversity(UniversityVO universityVO){
        return ServiceFactory.getInstance().getCourseService().findCoursesByUniversity(universityVO, em);
    }
    
    public List<CourseVO> findCoursesByProfessor(ProfessorVO professorVO){
        return ServiceFactory.getInstance().getCourseService().findCoursesByProfessor(professorVO, em);
    }
    
    /*
     *
     * Metodos de las categorias
     * 
     */
    
    public void createCategory(CategoryVO categoryVO){
        ServiceFactory.getInstance().getCategoryService().create(categoryVO, em);
    }

    public void updateCategory(CategoryVO categoryVO) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getCategoryService().update(categoryVO, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    //problemas con orphan relationship
    public void deleteCategory(int id) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getCategoryService().delete(id, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }

    public List<CategoryVO> getAllCategoriesVO(){
        return ServiceFactory.getInstance().getCategoryService().findAll(em);
    }
    
    public List<CategoryVO> getAllCategoriesVOInRange(int begin, int end){
        return ServiceFactory.getInstance().getCategoryService().findRange(begin, end, em);
    }

    public CategoryVO getCategoryVOById(int id) throws NotExistingObjectException{
        try {
            return ServiceFactory.getInstance().getCategoryService().findById(id, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    /*
     *
     * Metodos de los usuarios
     * 
     */
    
    public UserVO logIntoPlatform(UserVO userVO) throws NotExistingObjectException, IncorrectPasswordException{
        try {
            UserVO userVOfromServer = ServiceFactory.getInstance().getUserService().findById(userVO.getUsername(), em);
            if(userVO.getPassword().compareTo(userVOfromServer.getPassword()) != 0) {
                throw new IncorrectPasswordException();
            }
            return userVOfromServer;
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public void createUser(UserVO user){
        ServiceFactory.getInstance().getUserService().create(user, em);
    }
    
    public UserVO findUser(String name) throws NotExistingObjectException{
        try {
            return ServiceFactory.getInstance().getUserService().findById(name, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }

    /*
     *
     * Metodos de las Universidades
     * 
     */
    
    public void createUniversity(UniversityVO universityVO){
        ServiceFactory.getInstance().getUniversityService().create(universityVO, em);
    }
    
    public UniversityVO findUniversity(String id) throws NotExistingObjectException{
        try {
            return ServiceFactory.getInstance().getUniversityService().findById(id, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public List<UniversityVO> getAllUniversityVO(){
        return ServiceFactory.getInstance().getUniversityService().findAll(em);
    }
    
    public List<UniversityVO> getAllUniversitiesVOInRange(int begin, int end){
        return ServiceFactory.getInstance().getUniversityService().findRange(begin, end, em);
    }
    
    public void deleteUniversity(int id) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getUniversityService().delete(id, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public void updateUniversity(UniversityVO universityVO) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getUniversityService().update(universityVO, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    /*
     *
     * Metodos de los profesores
     * 
     */
    
    public void createProfessor(ProfessorVO professorVO){
        ServiceFactory.getInstance().getProfessorService().create(professorVO, em);
    }
    
    public List<ProfessorVO> getAllProfessorsVO(){
        return ServiceFactory.getInstance().getProfessorService().findAll(em);
    }
    
    public List<ProfessorVO> getAllProfessorsVOInRange(int begin, int end){
        return ServiceFactory.getInstance().getProfessorService().findRange(begin, end, em);
    }
    
    public void deleteProfessor(int professorId) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getProfessorService().delete(professorId, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public ProfessorVO findProfessorVOById(String username) throws NotExistingObjectException{
        try {
            return ServiceFactory.getInstance().getProfessorService().findById(username, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public void updateProfessor(ProfessorVO professorVO) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getProfessorService().update(professorVO, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public List<ProfessorVO> findProfessorsByUniversity(UniversityVO universityVO){
        return ServiceFactory.getInstance().getProfessorService().findProfessorsByUniversityUserName(universityVO.getUserName(), em);
    }
    
    /**
     * 
     * Métodos de los nodos
     * 
     */
    
    /*
     * Si est&aacute; directamente relacionado con un curso
     * establecer el curso, si no poner nada en el m&eacute;todo
     * <i>setCourse(CourseVO course)</i>
     * 
     */
    public void createNode(NodeVO nodeVo){
        ServiceFactory.getInstance().getNodeService().create(nodeVo, em);
    }
    
    public void updateNode(NodeVO nodeVO) throws NotExistingObjectException{
        try{
            ServiceFactory.getInstance().getNodeService().update(nodeVO, em);
        }catch(ObjectNotFoundException ex){
            throw new NotExistingObjectException();
        }
    }
    
    public void deleteNode(int id) throws NotExistingObjectException{
        try {
            ServiceFactory.getInstance().getNodeService().delete(id, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public NodeVO findNodeById(int id) throws NotExistingObjectException{
        try {
            return ServiceFactory.getInstance().getNodeService().findById(id, em);
        } catch (ObjectNotFoundException ex) {
            throw new NotExistingObjectException();
        }
    }
    
    public List<NodeVO> findNodesByParent(NodeVO nodeVO){
        return ServiceFactory.getInstance().getNodeService().findNodesByParent(nodeVO, em);
    }
    
    public List<NodeVO> findNodesByCourse(CourseVO courseVO){
        return ServiceFactory.getInstance().getNodeService().findNodesByCourse(courseVO, em);
    }
    
    /**
     * 
     * Métodos de buscas con similitud
     * 
     */
    public List<ResultObject> findEverything(String query){
        try {
            return ServiceFactory.getInstance().getFinderService().findElements(query, em);
        } catch (Exception ex) {
           return new ArrayList<ResultObject>(); 
        }
    }
}
